import base64
import json
from datetime import datetime, timedelta, timezone
import gridfs
import requests
from bson import ObjectId
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorGridFSBucket
from core.config import settings
from core.logger import log
import httpx
# 全局数据库连接池
_client = AsyncIOMotorClient(settings.MONGODB_URL)
_db = _client[settings.DB_NAME]


async def get_gridfs():
    return AsyncIOMotorGridFSBucket(_db)

# 使用GridFS存储图片数据
async def store_image_in_gridfs(binary_data, filename, metadata=None):
    """
    使用MongoDB GridFS存储二进制图片数据
    参数:
    - binary_data: 二进制图片数据
    - filename: 文件名
    - metadata: 额外的元数据
    - db: 数据库连接
    - fs: GridFS实例
    返回:
    - file_id: GridFS中的文件ID
    """
    fs = await get_gridfs()

    # 准备元数据
    if metadata is None:
        metadata = {}

    metadata.update({
        'content_type': 'image/jpeg',
        'upload_date': datetime.now(timezone(timedelta(hours=8))),
        'filename': filename
    })
    file_id = ObjectId()
    await fs.upload_from_stream_with_id(file_id, filename, binary_data, metadata=metadata)
    return file_id


# 从GridFS获取图片数据
async def get_image_from_gridfs(file_id):
    """
    从MongoDB GridFS获取二进制图片数据

    参数:
    - file_id: GridFS中的文件ID
    - db: 数据库连接
    - fs: GridFS实例

    返回:
    - binary_data: 二进制图片数据
    - metadata: 文件元数据
    """
    fs = await get_gridfs()
    # 获取文件
    if isinstance(file_id, str):
        file_id = ObjectId(file_id)

    # 获取文件信息
    grid_out = await fs.open_download_stream(file_id)

    # 读取二进制数据
    chunks = []
    async for chunk in grid_out:
        chunks.append(chunk)
    binary_data = b''.join(chunks)

    metadata = {
        'filename': grid_out.filename,
        'content_type': grid_out.metadata.get('content_type', 'application/octet-stream'),
        'upload_date': grid_out.upload_date,
        'length': grid_out.length
    }

    return binary_data, metadata


async def get_image_bytes_or_base64(data:dict[str, str], type: int= 1):
        """
        获取图片数据：type==1表示返回二进制数据（默认）
                    type==2表示返回base64数据
        参数：data:dict
                data["Key"]
                data["FromUserName"]
                data["MsgId"]
                data["ToUserName"]
        """
        url = f"{settings.BASE_URL}/message/GetMsgBigImg?key={data["Key"]}"

        total_length = 0
        # 直接收集解码后的二进制数据
        binary_chunks = []
        net_len = 0
        ran_num= 30
        async with httpx.AsyncClient() as client:
            for i in range(0, ran_num):
                start_pos = i * net_len
                data = {
                    "CompressType": 0,
                    "FromUserName": f"{data["FromUserName"]}",
                    "MsgId": int(data["MsgId"]),
                    "Section": {
                        "DataLen": 61440,
                        "StartPos": start_pos,
                    },
                    "ToUserName": f"{data["ToUserName"]}",
                    "TotalLen": total_length
                }
                log.info(f"请求数据：{data}")
                response = await client.post(url, json=data)
                # response = requests.post(url, json=data)

                try:
                    res = response.json()
                    if "Data" in res and "Data" in res["Data"] and "Buffer" in res["Data"]["Data"]:
                        buffer = res["Data"]["Data"]["Buffer"]
                        # 立即解码每个数据块
                        try:
                            # 确保base64字符串长度是4的倍数
                            padding_needed = len(buffer) % 4
                            if padding_needed > 0:
                                buffer += '=' * (4 - padding_needed)

                            binary_data = base64.b64decode(buffer)
                            binary_chunks.append(binary_data)
                            # print(f"获取并解码第 {i+1}/{4} 块: 原始长度={len(buffer)}, 解码后长度={len(binary_data)}")
                            net_len = res["Data"]["DataLen"]
                            total_length = res["Data"]["TotalLen"]
                        except Exception as e:
                            print(f"解码数据块 {i + 1} 时出错: {e}")
                    else:
                        print(f"错误: 返回数据格式不正确: {json.dumps(res, ensure_ascii=False)}")
                        break
                except Exception as e:
                    print(f"处理响应时出错: {e}")
                    print(f"原始响应内容: {response.text[:200]}...")

        # 将所有二进制数据块合并
        if binary_chunks:
            complete_binary = b''.join(binary_chunks)
            if type == 2:
                # 将二进制数据编码为base64
                base = base64.b64encode(complete_binary).decode()
                return base
            # 返回二进制数据
            return complete_binary
        else:
            print("没有成功获取任何数据块")
            return None